package com.jvup.common.support.base;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.Fragment;

/**
 * 项目内基础Fragment，提供一些同一行为。
 * @param <B> viewDataBinder 具体类型
 */
public abstract class BaseFragment<B extends ViewDataBinding> extends Fragment {

    /**
     * viewDataBinder 提供一个页面中View与Data的绑定器，是一个存放 UI（View） 和 Data（model行为）等关联的容器，
     * 并协助完成关联绑定和双向通知观察者，该对象会在第一次调用 {@link #viewDataBinder(LayoutInflater,ViewGroup)} 时完成初始化，一般在 {@link #onCreateView} 时创建。
     */
    private B viewDataBinder;

    /**
     * Fragment 页面使用的布局资源ID，期望在每个继承 Fragment 中指定，该ID会用来参与 {@link #viewDataBinder(LayoutInflater,ViewGroup)} 的构建，已完成指定的页面构建。
     * @return 页面的布局资源ID
     */
    public abstract int layoutRid();

    /**
     * 提供一个开放的 viewDataBinder 容器访问方法，由于 Fragment 需要在 {@link #onCreateView} 中构建所以该方法可能返回null。
     * @return {@link ViewDataBinding} viewDataBinder 视图数据绑定器，对于页面 View 或 Model 使用应该尽可能使用该方法来操作
     */
    public B viewDataBinder() {
        return viewDataBinder;
    }

    /**
     * 获得 viewDataBinder 容器，如果页面没有 viewDataBinder 则完成页面绑定。
     * 使用从 {@link #layoutRid layoutRid()} 方法提供的布局ID完成布局加载，只在首次调用时加载布局，该方法是线程安全的。
     * 该方法默认会在 {@link #onCreateView} 方法中被调用，并且加载布局返回 rootView，
     * 对于 viewDataBinder 访问可以使用 {@link #viewDataBinder()},除非期望得到一个稳定的返回，可以考虑该方法并提供可靠的参数，
     * 例如重写 {@link #onCreateView} 方法时。
     * @return viewDataBinder 视图数据绑定器
     */
    protected synchronized B viewDataBinder(@NonNull LayoutInflater inflater, @Nullable ViewGroup container) {
        if(null == viewDataBinder) {
            viewDataBinder = DataBindingUtil.inflate(inflater, layoutRid(),container,false);
            viewDataBinder.setLifecycleOwner(getActivity());
        }
        return viewDataBinder;
    }

    /**
     * 重写该方法时应该使用 {@link #viewDataBinder(LayoutInflater,ViewGroup)} 来完成加载布局返回 rootView的功能。
     */
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//        return super.onCreateView(inflater, container, savedInstanceState);
        return viewDataBinder(inflater,container).getRoot();
    }
}
